﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;
using System.Collections;

namespace XSerialization
{
    public class XSerializerContext
    {
        IEnumerable<IPattern> patterns;
        public IEnumerable<IPattern> Patterns
        {
            get
            {
                if (patterns == null)
                {
                    patterns = GetPatterns();
                }
                return patterns;
            }
            set 
            {
                patterns = value;
            }
        }
        private IEnumerable<IPattern> GetPatterns()
        {
            yield return new NullPattern();
            yield return new CircularReferencePattern();
            yield return new SimplePattern();
            yield return new EnumerablePattern();
            yield return new ObjectPattern();
        }

        public XmlWriter Writer { get; set; }

        HashSet<object> processedObjects = new HashSet<object>();
        public HashSet<object> ProcessedObjects
        {
            get
            {
                return processedObjects;
            }
        }

        public void Serialize(object o)
        {
            Patterns.First(p => p.Match(o, this)).Process(o, this);
        }
    }

    public class XSerializer
    {
        public static string Serialize<T>(T obj)
        {
            var result = new StringBuilder();
            using (var writer = XmlWriter.Create(result))
            {
                Serialize(obj, writer);
            }
            return result.ToString();
        }

        public static void Serialize(object obj, XmlWriter writer)
        {
            XSerializerContext c = new XSerializerContext() { Writer = writer };
            c.Writer.WriteStartElement(Naming.GetObjectName(obj));
            c.Serialize(obj);
            c.Writer.WriteEndElement();
        }
    }
}
